#include "car_lib.h"

void construirCarro(GLdouble ang_canon,GLdouble ang_ruedas,GLfloat rojo,
                                GLfloat verde,GLfloat azul, GLint anim_canon){
    
    glPushMatrix();
    
    glRotatef(180,1,0,0);
    glRotatef(90,0,1,0);
    
    // cañon1!!!
    glColor3f(0.50,0.45,0.45);
    glPushMatrix();
        glTranslatef(0.25,-0.15,-0.4);
        glRotatef(ang_canon,1.0,0.0,0.0);        
        gluCylinder(gluNewQuadric(),0.05,0.05,0.5,10,10);
        // color de los aritos
        glColor3f(1,1,0);
        if (anim_canon) {
            glutSolidTorus(0.01,anim_canon/500.0,10,10);
            glPushMatrix();
                glTranslatef(0.0,0.0,-0.3);
                glutSolidTorus(0.01,anim_canon/1000.0,10,10);
            glPopMatrix();
            glPushMatrix();
                glTranslatef(0.0,0.0,-0.5);
                glutSolidTorus(0.01,anim_canon/1500.0,10,10);
            glPopMatrix();
            // color del cono de fuego
            glColor3f(1.0,0.3,0.0);
            glPushMatrix();
                glRotatef(180,0.0,1.0,0.0);
                glutSolidCone(0.05,anim_canon/100.0,10,10);
            glPopMatrix();
        }
    glPopMatrix();
    
    // cañon2!!!
    glColor3f(0.50,0.45,0.45);
    glPushMatrix();
        glTranslatef(0.0,0.15,-0.4);
        glRotatef(270,0.0,1.0,0.0);
        glRotatef(45,1.0,0.0,0.0);        
        gluCylinder(gluNewQuadric(),0.02,0.02,0.5,10,10);
    glPopMatrix();
    glColor3f(0.50,0.45,0.45);
    glPushMatrix();
        glTranslatef(-0.35,-0.2,-0.5);
        gluCylinder(gluNewQuadric(),0.05,0.05,0.5,10,10);
    glPopMatrix();
    
    // "cuerpo abajo"
    glColor3f(rojo,verde,azul);
    glPushMatrix();
        glScalef(0.5,0.3,1);
        glutSolidCube(1);
    glPopMatrix();
    
    // "cuerpo arriba"
    glColor3f(0.60,0.55,0.55);
    glPushMatrix();
        glScalef(0.4,0.3,0.5);
        glTranslatef(0,-0.3,-0.35);
        glutSolidCube(1);
    glPopMatrix();
    
    // ruedas
    glColor3f(0,0,0);
    // rueda1
    glPushMatrix();
        glTranslatef(0.25,0.2,0.3);
        glRotatef(ang_ruedas,0.0,1.0,0.0);
        glScalef(0.1,0.2,0.2);
        glutSolidSphere(1,10,10);
    glPopMatrix();
    // rueda2
    glPushMatrix();
        glTranslatef(-0.25,0.2,0.3);
        glRotatef(ang_ruedas,0.0,1.0,0.0);
        glScalef(0.1,0.2,0.2);
        glutSolidSphere(1,10,10);
    glPopMatrix();
    // rueda3
    glPushMatrix();
        glTranslatef(0.25,0.2,-0.3);
        glScalef(0.1,0.2,0.2);
        glutSolidSphere(1,10,10);
    glPopMatrix();
    // rueda4
    glPushMatrix();
        glTranslatef(-0.25,0.2,-0.3);
        glScalef(0.1,0.2,0.2);
        glutSolidSphere(1,10,10);
    glPopMatrix();
    
    glPopMatrix();
}

GLdouble angTarg(GLdouble ref_x,GLdouble ref_z,GLdouble targ_x,GLdouble targ_z){
    GLdouble ang_target;
    ang_target = atan((ref_x-targ_x)/(ref_z-targ_z));
    if (targ_z>= ref_z){
        ang_target = 270+ang_target*R2G;
    }
    else {
        ang_target = 90+ang_target*R2G;
    }
    return ang_target;
}

int whereIs(GLdouble x,GLdouble z){
    int i;
    for(i=0;i<nn;i++){
        if(enNodo(x,z,&nodos[i])) return i;
    }
    return -1;
}

int hayPared(GLdouble xo,GLdouble zo,GLdouble xt,GLdouble zt){
    int i;
    for(i=0;i<nr;i++){
        if(rectas[i].hor){
            if(((xo > rectas[i].xi && xo < rectas[i].xf) ||
                (xt > rectas[i].xi && xt < rectas[i].xf)) &&
                ((zo > (rectas[i].zi+2) && zt < (rectas[i].zf-2)) ||
                (zt > (rectas[i].zi+2) && zo < (rectas[i].zf-2)))) return 1;
        }
        else if(((zo > rectas[i].zi && zo < rectas[i].zf) ||
                    (zt > rectas[i].zi && zt < rectas[i].zf)) &&
                    ((xo > (rectas[i].xi+2) && xt < (rectas[i].xf-2)) ||
                    (xt > (rectas[i].xi+2) && xo < (rectas[i].xf-2)))) return 1;
    }
    for(i=0;i<nramp;i++){
        if(((xo > rampas[i].xi && xo < rampas[i].xf) ||
            (xt > rampas[i].xi && xt < rampas[i].xf)) &&
            ((zo > (rampas[i].zi+2) && zt < (rampas[i].zf-2)) ||
            (zt > (rampas[i].zi+2) && zo < (rampas[i].zf-2)))) return 1;
        else if(((zo > rampas[i].zi && zo < rampas[i].zf) ||
                    (zt > rampas[i].zi && zt < rampas[i].zf)) &&
                    ((xo > (rampas[i].xi+2) && xt < (rampas[i].xf-2)) ||
                    (xt > (rampas[i].xi+2) && xo < (rampas[i].xf-2)))) return 1;
    }
    for(i=0;i<nedif;i++){
        if(((xo > edifs[i].xi && xo < edifs[i].xf) ||
            (xt > edifs[i].xi && xt < edifs[i].xf)) &&
            ((zo > (edifs[i].zi+2) && zt < (edifs[i].zf-2)) ||
            (zt > (edifs[i].zi+2) && zo < (edifs[i].zf-2)))) return 1;
        else if(((zo > edifs[i].zi && zo < edifs[i].zf) ||
                    (zt > edifs[i].zi && zt < edifs[i].zf)) &&
                    ((xo > (edifs[i].xi+2) && xt < (edifs[i].xf-2)) ||
                    (xt > (edifs[i].xi+2) && xo < (edifs[i].xf-2)))) return 1;
    }
    return 0;
}

double mirar(Car* car,GLdouble x,GLdouble z){
    double diff,dist = 400;
    GLdouble angulo = angTarg(car->x,car->z,x,z);
    diff = fabs(angulo-car->vision);
    if(diff < 30){
        dist = sqrt(pow(car->x-x,2)+pow(car->z-z,2));
        if(dist >= 300 || hayPared(car->x,car->z,x,z)) dist = 400;
    }
    else if(sqrt(pow(car->x-x,2)+pow(car->z-z,2)) < 5 &&
                !hayPared(car->x,car->z,x,z))
        dist = sqrt(pow(car->x-x,2)+pow(car->z-z,2));
    return dist;
}

GLint danger(Car* car,Bomb** bombas){
    double dist_bomb, aux_d;
    int i,j,close;
    close = -1;
    dist_bomb = 20;
    for (j=b,i=0; i<20; j++,i++){
        j%=20;
        if (bombas[19-j] == NULL) continue;
        else{
            if(fabs(bombas[19-j]->y-car->y) < 1)
                aux_d = mirar(car,bombas[19-j]->x,bombas[19-j]->z);
            else
                aux_d = mirar(car,bombas[19-j]->tx,bombas[19-j]->tz);
            if(aux_d < dist_bomb){
                dist_bomb = aux_d;
                close = 19-j;
            }
        }
    }
    return close;
}

int hayGota(Car* car,OilTrace* rastro){
    //Proximo nodo con rastro de aceite
    int i,j,aux,gota = -1;
    double dist;
    for (i=rastro->gotaP,j=0;j<200;i++,j++){
        i%=200;
        aux = whereIs(rastro->aceiteXZ[i][0],rastro->aceiteXZ[i][1]);
        if(nodos[aux].yo_aceite){
            dist = mirar(car,rastro->aceiteXZ[i][0],rastro->aceiteXZ[i][1]);
            if(dist != 400)
                gota = aux;
        }
    }
    return gota;
}

void decide(Car* com,Bomb** bombas,OilTrace* rastro){
    double dist = mirar(com,state.car->x,state.car->z);
    state.bomb = danger(com,bombas);
    int gota = hayGota(com,rastro);
    if(state.bomb != -1){ state.id = 0; printf(" Huir de Bomba \n"); }
    if(state.id == 0){ //Huir (bombas)
        if(state.bomb == -1){ state.id = 1; printf(" Vagar \n"); }
        else flee(com,bombas[state.bomb]->x,bombas[state.bomb]->z,
                    bombas[state.bomb]->m_dir);
    }
    if(state.id == 1){ //Vagar
        if(dist != 400){
            if(com->vidas == 1){ state.id = 5; printf(" Huir del Carro \n"); }
            else{ state.id = 3;  printf(" Seguir al Carro \n"); }
        }
        else if(com->vidas == 1){ state.id = 6; printf(" Recuperar Vida \n"); }
        else if(gota != -1){ state.id = 2; printf(" Seguir el Rastro \n"); }
        else if(state.car->vidas == 1 || state.car->balas < 2){
            state.id = 8;
            printf(" Hacer Emboscada \n");
        }
        else wander(com);
    }
    if(state.id == 8){ //Emboscada
        if(dist != 400){ state.id = 3; printf(" Seguir al Carro \n"); }
        else if(gota != -1){ state.id = 2; printf(" Seguir el Rastro \n"); }
        else if(state.car->vidas == 1) seek(com,nodos[vida].v1);
        else if(state.car->balas < 3) seek(com,nodos[amno].v1);
        else{ state.id = 1; printf(" Vagar \n"); }
    }
    if(state.id == 2){ //Seguir (rastro)
        if(dist != 400){ state.id = 3; printf(" Seguir al Carro \n"); }
        else if(gota == -1){ state.id = 1; printf(" Vagar \n"); }
        else seek(com,gota);
    }
    if(state.id == 3){ //Seguir (carro)
        if(dist == 400){ state.id = 2; printf(" Seguir el Rastro \n"); }
        else if(dist <= 50){ state.id = 4; printf(" Disparar \n"); }
        else seek(com,whereIs(state.car->x,state.car->z));
    }
    if(state.id == 4){ //Disparar
        if(com->vidas == 1){ state.id = 5; printf(" Huir del Carro \n"); }
        else if(!com->balas){ state.id = 7; printf(" Buscar Municiones \n"); }
        else if(dist > 50){ state.id = 3; printf(" Seguir al Carro \n"); }
        else aim(com,state.car,bombas);
    }
    if(state.id == 5){ //Huir (carro)
        if(dist == 400){ state.id = 6; printf(" Recuperar Vida \n"); }
        else flee(com,state.car->x,state.car->z,state.car->vision);
    }
    if(state.id == 6){ //Buscar Item (vida)
        if(dist != 400){ state.id = 5; printf(" Huir del Carro \n"); }
        else if(com->vidas == 3){ state.id = 1; printf(" Vagar \n"); }
        else seek(com,vida);
    }
    if(state.id == 7){ //Buscar Item (balas)
        if(com->balas){ state.id = 1; printf(" Vagar \n"); }
        else seek(com,amno);
    }
}

void dibujaVel(GLdouble v_mag, GLint tu){
    GLint vel = (int)v_mag;
    GLint i;
    for(i=0;i<vel;i++){
        glPushMatrix();
            glColor3f(i/50.0,1-i/50.0,0);
            glTranslatef(0,i/50.0,0);
            glRotatef(90,1,0,0);
            gluCylinder(gluNewQuadric(),0.05,0.05,0.01,15,15);
        glPopMatrix();
    }
    for(i=vel;i<0;i++){
        glPushMatrix();
            glColor3f(i*(-1)/5.0,1-i*(-1)/5.0,0);
            glTranslatef(0,i/50.0,0);
            glRotatef(90,1,0,0);
            gluCylinder(gluNewQuadric(),0.05,0.05,0.01,15,15);
        glPopMatrix();
    }
}

void align(Car* car,GLdouble ang_target){
    GLdouble diff;
    diff = fabs(ang_target - car->vision);
    car->acelera = 0;
    if (diff >= 180.0){
        if (ang_target > car->vision) car->a_mag = -90;
        else car->a_mag = 90;
    }
    else {
        if (ang_target > car->vision) car->a_mag = 90;
        else car->a_mag = -90;
    }
}

void seekN(Car* com,GLdouble x, GLdouble z){
    GLdouble angulo;
    angulo = angTarg(com->x,com->z,x,z);
    if (angulo-2 < com->vision && com->vision < angulo+2){
        double dist = sqrt(pow(x-com->x,2)+pow(z-com->z,2));
        com->a_mag = 0;
        if (dist >= 4)
            com->acelera=1;
        else {
            if(com->time_units>=6){
                com->time_units -=60;
            }
            com->acelera=0;
        }
    }
    else align(com,angulo);
}

void seek(Car* com,int target){
    com->nodot = target;
    if(com->nodot == -1){
        state.id = 1;
        com->nodot = rand()%nn;
    }
    else{
        haciaDonde(com);        
        seekN(com,nodos[com->nodosig].x,nodos[com->nodosig].z);
    }
}

void wander(Car* com){
    if (com->nodo == com->nodot) com->nodot = rand()%nn;
    haciaDonde(com);        
    seekN(com,nodos[com->nodosig].x,nodos[com->nodosig].z);
}

void flee(Car* com,GLdouble x,GLdouble z,GLdouble dir){
    /*int nodo_b = whereIs(x,z);
    com->nodot = nodos[nodos[nodo_b].v1].v1;
    haciaDonde(com);
    seekN(com,nodos[com->nodosig].x,nodos[com->nodosig].z);*/
    GLdouble angulo,dist;
    dist = sqrt(pow(x-com->x,2)+pow(z-com->z,2));
    angulo = fabs(180-angTarg(com->x,com->z,x,z));
    align(com,angulo);
    if (dist <= 30)
        com->acelera=1;
    else {
        if(com->time_units>=6){
            com->time_units -=15;
        }
        com->acelera=0;
    }
}

// Calcular el angulo de disparo con una ecuacion de 2do grado!! :D
void aim(Car* com,Car* yo,Bomb** bombas){
    double dist = sqrt(pow(yo->x-com->x,2)+pow(yo->z-com->z,2));
    if (!com->anim_canon){
        GLdouble angulo;
        angulo = angTarg(com->x,com->z,yo->x,yo->z);
        if (angulo-2 < com->vision && com->vision < angulo+2){
            if (dist<50){
                if (com->v_mag > yo->v_mag || dist <= 20) com->ang_canon -= 10;
                else com->ang_canon +=10;
                if (com->ang_canon > 90) com->ang_canon = 90;
                if (com->ang_canon < 0) com->ang_canon = 0;
                if (com->balas){
                    com->balas--;
                    com->anim_canon = 1;
                    dispara(com,bombas,0);
                }
                else printf(" Recargar!! \n");
            }
            if (dist >= 50 && dist <= 70){
                if(com->balas){
                    com->balas--;
                    com->anim_canon = 1;
                    dispara(com,bombas,0);
                }
                else printf(" Recargar!! \n");
            }
        }
        else align(com,angulo);
    }
}

void dispara(Car* car, Bomb** bombas, GLint quien){
    bombas[b] = crearBomba( car->x+sin(car->vision/R2G)*0.25,
                            car->y+0.3,
                            car->z+cos(car->vision/R2G)*0.25,
                            car->vision,car->ang_canon,
                            car->v_mag,car->time_units,quien);
    b++;
    b = b%20;
}

void inRampa(Car* aux){
    if(!aux->salta){
        GLint i;
        for(i=0;i<nramp;i++){
            if (rampas[i].xi <= aux->x && aux->x <= rampas[i].xf && 
                rampas[i].zi <= aux->z && aux->z <= rampas[i].zf) {
                if (rampas[i].normal)
                    aux->y = ((0 - 10.38)/(rampas[i].zi - rampas[i].zf))*(aux->z - rampas[i].zi);
                else
                    aux->y = ((0 - 10.38)/(rampas[i].zf - rampas[i].zi))*(aux->z - rampas[i].zf);
            }
        }
    }
}

GLdouble altura(GLdouble x, GLdouble z){
    GLint i;
    for(i=0;i<nramp;i++){
        if (rampas[i].xi <= x && x <= rampas[i].xf && 
            rampas[i].zi <= z && z <= rampas[i].zf) {
            if (rampas[i].normal)
                return ((0 - 10.38)/(rampas[i].zi - rampas[i].zf))*(z - rampas[i].zi);
            else
                return ((0 - 10.38)/(rampas[i].zf - rampas[i].zi))*(z - rampas[i].zf);
        }
    }
    return 0;
}

void gravedad(Car* aux){
    aux->vy = aux->vy-(15* t);
    aux->y += ((2+(aux->vy/40))* t)-((15* t * t)/2);
    if(aux->y <= (altura(aux->x,aux->z))){
        aux->y = altura(aux->x,aux->z);
        aux->vy = 0;
        aux->salta = 0;
        t = 0;
    }
}

void caer(Car* car){
    GLint i,flag;
    flag = 0;
    for(i=0;i<nramp;i++){
        if((rampas[i].xi <= car->x && car->x <= rampas[i].xf && 
                rampas[i].zi <= car->z && car->z <= rampas[i].zf)){
                flag = 1;
        }
    }
    if(!flag && car->y > 0 && !car->salta){
        t += 0.02;
        gravedad(car);
    }
}

void reload(Car* car){
    if(car->balas < 10){
        car->balas += 5;
        if(car->balas > 10) car->balas = 10;
        setItems();
    }
    else printf(" Municion Completa! \n");
}

void recover(Car* car){
    if(car->vidas < 3){
        car->vidas++;
        setItems();
    }
    else printf(" Vidas Completas! \n");
}

void update(Car* aux, Car* vs){

    if (!enNodo(aux->x,aux->z,&nodos[aux->nodo])) {
        aux->nodo = aux->nodosig;
        pasos++;
        nodos[whereIs(aux->x,aux->z)].time = pasos;
    }

    if(sqrt(pow(aux->x-nodos[amno].x,2)+pow(aux->z-nodos[amno].z,2)) < 1)
        reload(aux);
    if(sqrt(pow(aux->x-nodos[vida].x,2)+pow(aux->z-nodos[vida].z,2)) < 1)
        recover(aux);

    GLdouble up_x,up_z;
    
    if (aux->anim_canon){
        aux->anim_canon+=10;
        if (aux->anim_canon > 100){
            aux->anim_canon=0;
        }
    }
    
    if (aux->acelera == 1){
        if (aux->time_units<0)
            aux->time_units += 20;
        else 
            aux->time_units += 15;
        if (aux->time_units > 2000){
            aux->time_units = 2000;
        }
    }
    if (aux->acelera == -1){
        if (aux->time_units>0)
            aux->time_units -= 25;
        else 
            aux->time_units -= 15;
        if (aux->time_units < -200){
            aux->time_units = -200;
        }
    }
    if (aux->acelera == 0){
        if (aux->time_units > 0) aux->time_units -= 5;
        if (aux->time_units < 0) aux->time_units += 5;
    }
    up_x = cos((360-(aux->vision))/R2G)*aux->v_mag*0.025;
    up_z = sin((360-(aux->vision))/R2G)*aux->v_mag*0.025;
    if(!colisiona(aux->x+up_x,aux->z+up_z,aux->y,vs)){
        aux->v_mag = aux->time_units*0.025;
        aux->vision += aux->a_mag * 0.025;
        if(aux->salta) salta(aux);
        //newPos(&(aux->x),&(aux->z),up_x,up_z);
        aux->x += up_x;
        aux->z += up_z;
        inRampa(aux);
        caer(aux);
    }
    else{
        // producir respuesta a la colision
        aux->v_mag *= -0.1;
        aux->a_mag *= -1;
        aux->time_units *= -0.1;
        aux->acelera = -1;
    }
    while(aux->vision>=360 || aux->vision<0){
        if (aux->vision>=360) aux->vision-=360;
        else aux->vision+=360;
    }
}

int colisiona(GLdouble pos_x, GLdouble pos_z, GLdouble pos_y, Car* car){
    GLdouble dist_xz,dist_y;
    // colision con enemigo
    dist_y = fabs(pos_y - car->y);
    if(dist_y < 0.2){
        dist_xz = sqrt(pow(pos_x-car->x,2)+pow(pos_z-car->z,2));
        if(dist_xz <= 0.90) return 1;
    }
    // colision con fin del mapa
    if(pos_x > 199.25 || pos_x < -199.25){
        return 1;
    }
    if(pos_z > 199.25 || pos_z < -199.25){
        return 1;
    }
    // colision con paredes
    GLint i;
    for(i=0;i<nr;i++){
        if (rectas[i].hor){
            if (pos_x >=rectas[i].xi && pos_x <= rectas[i].xf){
                if (fabs(pos_z-rectas[i].zf) < 0.75) {
                    if (pos_y < rectas[i].a) return 1;
                }
                else {
                    if (pos_x < rectas[i].xi){
                        if (sqrt(pow(pos_x-rectas[i].xi,2)+pow(pos_z-rectas[i].zi,2)) < 0.75) {
                            if (pos_y < rectas[i].a) return 1;
                        }
                    }
                    else {
                        if (sqrt(pow(pos_x-rectas[i].xf,2)+pow(pos_z-rectas[i].zf,2)) < 0.75) {
                            if (pos_y < rectas[i].a) return 1;
                        }
                    }
                }
            }
        }
        else {
            if (pos_z >=rectas[i].zi && pos_z <= rectas[i].zf){
                if (fabs(pos_x-rectas[i].xf) < 0.75){
                    if (pos_y < rectas[i].a) return 1;
                }
                else {
                    if (pos_z < rectas[i].zi){
                        if (sqrt(pow(pos_x-rectas[i].xi,2)+pow(pos_z-rectas[i].zi,2)) < 0.75) {
                            if (pos_y < rectas[i].a) return 1;
                        }
                    }
                    else {
                        if (sqrt(pow(pos_x-rectas[i].xf,2)+pow(pos_z-rectas[i].zf,2)) < 0.75) {
                            if (pos_y < rectas[i].a) return 1;
                        }
                    }
                }
            }
        }
    }
    // choque con las rampas
    for(i=0; i < nramp; i++){
        if(pos_z > rampas[i].zi && pos_z < rampas[i].zf){
            if(pos_x < rampas[i].xi && rampas[i].xi - pos_x < 0.75) return 1;
            if(pos_x > rampas[i].xf && pos_x - rampas[i].xf < 0.75) return 1;
        }
        if(pos_x > rampas[i].xi && pos_x < rampas[i].xf){
            if(pos_y < 10){
                if(rampas[i].normal){
                    if(pos_z > rampas[i].zf && pos_z - rampas[i].zf < 0.75)
                    return 1;
                }
                else{
                    if(pos_z < rampas[i].zi && rampas[i].zi - pos_z < 0.75)
                    return 1;
                }
            }
        }
    }
    // choque con los edificios
    for(i=0; i < nedif; i++){
        if(pos_z > edifs[i].zi && pos_z < edifs[i].zf){
            if(pos_x < edifs[i].xi && edifs[i].xi - pos_x < 0.75) return 1;
            if(pos_x > edifs[i].xf && pos_x - edifs[i].xf < 0.75) return 1;
        }
        if(pos_x > edifs[i].xi && pos_x < edifs[i].xf){
            if(pos_z < edifs[i].zi && edifs[i].zi - pos_z < 0.75) return 1;
            if(pos_z > edifs[i].zf && pos_z - edifs[i].zf < 0.75) return 1;
        }
    }
    return 0;
}

void newPos(GLdouble *act_x,GLdouble *act_z,GLdouble new_x,GLdouble new_z){
    // Cuando choca con la pared conserva la velocidad y aceleracion!!
    if(*act_x < 199 && *act_x > -199){
        if(*act_x+new_x < 199 && *act_x+new_x > -199)
            *act_x += new_x;
    }
    if(*act_z < 199 && *act_z > -199){
        if(*act_z+new_z < 199 && *act_z+new_z > -199)
            *act_z += new_z;
    }
}

void salta(Car* aux){
    if(aux->vy == 0) aux->vy = fabs(aux->v_mag)*(sin(3.14/5)/cos(3.14/5));
    t += 0.02;
    gravedad(aux);
}

void updateB(Bomb* aux){
    if (!aux->blow){
        GLdouble vx,vy;
        vx = cos(aux->v_dir/R2G)*aux->v_mag;
        vy = sin(aux->v_dir/R2G)*aux->v_mag;
        vy -= aux->time_units*0.025;
        if (vy<0 && !aux->bajando){
            vy = 0.0001;
            aux->time_units=0;
            aux->bajando=1;
        }
        newPos(&(aux->x),&(aux->z),(cos((360-aux->m_dir)/R2G)*vx*0.025),
                (sin((360-aux->m_dir)/R2G)*vx*0.025));
        aux->v_dir = atan(vy/vx)*R2G;
        aux->v_mag = vy/sin(aux->v_dir/R2G);
        aux->y += sin(aux->v_dir/R2G)*aux->v_mag*0.025;    
        if (aux->y<0) aux->blow = 1;
        aux->time_units++;
    }
}

void explota(Car* car,Bomb* bomb){
    // Si el carro esta en donde la bomba o el radio externo, prendo flag de dañado!
    GLdouble dist_y,dist_xz;
    dist_y = fabs(bomb->y-car->y);
    dist_xz = sqrt(pow(bomb->x-car->x,2)+pow(bomb->z-car->z,2));
    if(!car->hit){
        if(bomb->blow){
            if(dist_xz <= 2 && dist_y <= 2){
                // Game Over
                car->vidas = 0;
                car->hit = 1;
                bomb->hit = 1;
                printf("Pise una bomba!\n");
            }
            else if(dist_xz <= bomb->blow/10 && dist_y <= 1){
                // Vida Menos
                car->vidas -= 1;
                car->hit = 1;
                bomb->hit = 1;
                printf("Radio de danios, me quedan %d vidas\n",car->vidas);
            }
        }
        else if(dist_y < 0.3 && dist_xz < 0.5){
            // Game Over
            bomb->blow = 1;
            car->vidas = 0;
            car->hit = 1;
            bomb->hit = 1;
            printf("Me han disparado!\n");
        }
    }
}

void construirBomba(GLfloat rojo,GLfloat verde,GLfloat azul,GLdouble ang_bomb_z){
    // cuerpo de la bomba
    glPushMatrix();
        glTranslatef(-0.0,-0.15,0.0);
        glRotatef(ang_bomb_z,0.0,0.0,1.0);
        glPushMatrix();
            glColor3f(rojo,verde,azul);
            glScalef(1.0,0.4,0.4);
            glutSolidSphere(0.1,10,10);
        glPopMatrix();
        glColor3f(0.50,0.45,0.45);
        glBegin(GL_TRIANGLES);
            glVertex3f(-0.1,0.0,0.0);
            glVertex3f(-0.1,0.1,0.0);
            glVertex3f(0.0,0.0,0.0);
        glEnd();    
        glBegin(GL_TRIANGLES);
            glVertex3f(-0.1,0.0,0.0);
            glVertex3f(-0.1,-0.1,0.0);
            glVertex3f(0.0,0.0,0.0);
        glEnd();
        glBegin(GL_TRIANGLES);
            glVertex3f(-0.1,0.0,0.0);
            glVertex3f(-0.1,0.0,-0.1);
            glVertex3f(0.0,0.0,0.0);
        glEnd();
        glBegin(GL_TRIANGLES);
            glVertex3f(-0.1,0.0,0.0);
            glVertex3f(-0.1,0.0,0.1);
            glVertex3f(0.0,0.0,0.0);
        glEnd();    
    glPopMatrix();
    
}

Bomb* crearBomba(GLdouble x,GLdouble y,GLdouble z,GLdouble vision,
                 GLdouble canon,GLdouble vel,GLint tu,GLint quien){
    Bomb* new_b = (Bomb*)malloc(sizeof(Bomb));
    new_b->time_units = 0;
    new_b->bajando = 0;
    new_b->blow = 0;
    new_b->hit = 0;
    new_b->x = x;
    new_b->y = y;
    new_b->z = z;    
    new_b->m_dir = vision;    
    new_b->side = 0;
    new_b->quien = quien;
    //new_b->tx = 1000;
    GLdouble px,py;    
    if (canon == 0.0) canon = 0.1;
    //Esto era lo que hacia que la bala saliera hacia atras :)
    /*if (tu < 0) {
        if (new_b->m_dir >= 180) new_b->m_dir -= 180;
        else new_b->m_dir += 180;
        new_b->side = 1;
    }*/
    px = cos(canon/R2G)*20 + vel;
    py = sin(canon/R2G)*20;    
    new_b->v_dir = atan(py/px)*R2G;
    //Lo quite porque se veia raro cuando disparaba en retroceso
    //if (new_b->v_dir < 0) new_b->v_dir *= -1;
    new_b->v_mag = py/sin(new_b->v_dir/R2G);
    endPoint(new_b);
    char* who;
    if(quien) who = "yo";
    else who = "com";
    printf("%s ha disparado una bomba \n",who);
    return new_b;
}

void endPoint(Bomb* bomb){
        // crea una bomba auxiliar para hacer los calculos
        Bomb *aux = (Bomb*)malloc(sizeof(Bomb));
        aux->x = bomb->x;
        aux->y = bomb->y;
        aux->z = bomb->z;
        aux->v_dir = bomb->v_dir;
        aux->v_mag = bomb->v_mag;
        aux->m_dir = bomb->m_dir;
        aux->bajando = bomb->bajando;
        aux->time_units = bomb->time_units; 
        while(aux->y > 0){
            GLdouble vx,vy;
            vx = cos(aux->v_dir/R2G)*aux->v_mag;
            vy = sin(aux->v_dir/R2G)*aux->v_mag;
            vy -= aux->time_units*0.025;
            if (vy<0 && !aux->bajando){
                vy = 0.0001;
                aux->time_units=0;
                aux->bajando=1;
            }
            newPos(&(aux->x),&(aux->z),(cos((360-aux->m_dir)/R2G)*vx*0.025),
                    (sin((360-aux->m_dir)/R2G)*vx*0.025));
            aux->v_dir = atan(vy/vx)*R2G;
            aux->v_mag = vy/sin(aux->v_dir/R2G);
            aux->y += sin(aux->v_dir/R2G)*aux->v_mag*0.025;
            aux->time_units++;
            bomb->tx = aux->x;
            bomb->tz = aux->z;
        }
        free(aux);
}

void dibujaExplosion(GLint anim){
    glColor3f(0.6,0.4,0.4);
    glPushMatrix();
        glTranslatef(0.0,0.1,0.0);
        glRotatef(90,1.0,0.0,0.0);
        glutSolidTorus(0.01,anim/10,10,10);
    glPopMatrix();
    glColor3f(1.0,0.3,0.0);
    glPushMatrix();
        glTranslatef(0.0,-0.35,0.0);
        glRotatef(90,-1.0,0.0,0.0);
        glutSolidCone(0.5,anim/100.0,10,10);
    glPopMatrix(); 
    glPushMatrix();
        glTranslatef(0.0,anim/100.0,0.0);
        glRotatef(90,1.0,0.0,0.0);
        glutSolidCone(anim/100.0,1.0,10,10);
    glPopMatrix();   
    glPushMatrix();
        glTranslatef(0.0,anim/100.0,0.0);
        glScalef(1.0,0.4,1.0);
        glutSolidSphere(anim/75.0,10,10);
    glPopMatrix();   
}

// quick and dirty bitmap loader...for 24 bit bitmaps with 1 plane only.  
// See http://www.dcs.ed.ac.uk/~mxr/gfx/2d/BMP.txt for more info.
int cargarImagen(char *filename, Imagen *img) {
    
    FILE *file;
    unsigned long size;       // size of the image in bytes.
    unsigned long i;          // standard counter.
    unsigned short int planes;// number of planes in image (must be 1) 
    unsigned short int bpp;   // number of bits per pixel (must be 24)
    char temp;                // temporary color storage for bgr-rgb conversion.

    // make sure the file is there.
    if ((file = fopen(filename, "rb"))==NULL)
    {
	    printf("File Not Found : %s\n",filename);
	    return 0;
    }
    
    // seek through the bmp header, up to the width/height:
    fseek(file, 18, SEEK_CUR);

    // read the width
    if ((i = fread(&img->sizeX, 4, 1, file)) != 1) {
	    printf("Error reading width from %s.\n", filename);
	    return 0;
    }
    //printf("Width of %s: %ud\n", filename, img->sizeX);
    
    // read the height 
    if ((i = fread(&img->sizeY, 4, 1, file)) != 1) {
	    printf("Error reading height from %s.\n", filename);
	    return 0;
    }
    //printf("Height of %s: %ud\n", filename, img->sizeY);
    
    // calculate the size (assuming 24 bits or 3 bytes per pixel).
    size = img->sizeX * img->sizeY * 3;

    // read the planes
    if ((fread(&planes, 2, 1, file)) != 1) {
	    printf("Error reading planes from %s.\n", filename);
	    return 0;
    }
    if (planes != 1) {
	    printf("Planes from %s is not 1: %u\n", filename, planes);
	    return 0;
    }

    // read the bpp
    if ((i = fread(&bpp, 2, 1, file)) != 1) {
	    printf("Error reading bpp from %s.\n", filename);
	    return 0;
    }
    if (bpp != 24) {
	    printf("Bpp from %s is not 24: %u\n", filename, bpp);
	    return 0;
    }
	
    // seek past the rest of the bitmap header.
    fseek(file, 24, SEEK_CUR);

    // read the data. 
    img->data = (char*)malloc(size);
    if (img->data == NULL) {
	    printf("Error allocating memory for color-corrected image data");
	    return 0;	
    }

    if ((i = fread(img->data, size, 1, file)) != 1) {
	    printf("Error reading image data from %s.\n", filename);
	    return 0;
    }

    for (i=0;i<size;i+=3) { // reverse all of the colors. (bgr -> rgb)
	    temp = img->data[i];
	    img->data[i] = img->data[i+2];
	    img->data[i+2] = temp;
    }
    
    // we're done.
    return 1;
}

void cargarTextura(){
    Imagen *w1;
    w1 = (Imagen*)malloc(sizeof(Imagen));
    if (w1 == NULL) {
    	printf("Error: malloc de la imagen");
	    exit(0);
    }
    if (!cargarImagen("img/lol.bmp", w1)) {
        printf("Error: cargando la imagen");
	    exit(1);
    }
    Imagen *w2;
    w2 = (Imagen*)malloc(sizeof(Imagen));
    if (w2 == NULL) {
    	printf("Error: malloc de la imagen");
	    exit(0);
    }
    if (!cargarImagen("img/edif1.bmp", w2)) {
        printf("Error: cargando la imagen");
	    exit(1);
    }
    Imagen *w3;
    w3 = (Imagen*)malloc(sizeof(Imagen));
    if (w3 == NULL) {
    	printf("Error: malloc de la imagen");
	    exit(0);
    }
    if (!cargarImagen("img/edif2.bmp", w3)) {
        printf("Error: cargando la imagen");
	    exit(1);
    }
    Imagen *w4;
    w4 = (Imagen*)malloc(sizeof(Imagen));
    if (w4 == NULL) {
    	printf("Error: malloc de la imagen");
	    exit(0);
    }
    if (!cargarImagen("img/pared.bmp", w4)) {
        printf("Error: cargando la imagen");
	    exit(1);
    }
    Imagen *w5;
    w5 = (Imagen*)malloc(sizeof(Imagen));
    if (w5 == NULL) {
    	printf("Error: malloc de la imagen");
	    exit(0);
    }
    if (!cargarImagen("img/wood.bmp", w5)) {
        printf("Error: cargando la imagen");
	    exit(1);
    }
    
    glGenTextures(1, (GLuint*)&asfalto);
    glGenTextures(2, (GLuint*)&edificio);
    glGenTextures(1, (GLuint*)&pared);
    glGenTextures(1, (GLuint*)&madera);
    
    glBindTexture(GL_TEXTURE_2D, asfalto[0]);
    glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR);
    glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR);
    glTexImage2D(GL_TEXTURE_2D, 0, 3, w1->sizeX, w1->sizeY, 0, GL_RGB,GL_UNSIGNED_BYTE, w1->data);
    
    glBindTexture(GL_TEXTURE_2D, edificio[0]);
    glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR);
    glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR);
    glTexImage2D(GL_TEXTURE_2D, 0, 3, w2->sizeX, w2->sizeY, 0, GL_RGB,GL_UNSIGNED_BYTE, w2->data);
    
    glBindTexture(GL_TEXTURE_2D, edificio[1]);
    glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR);
    glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR);
    glTexImage2D(GL_TEXTURE_2D, 0, 3, w3->sizeX, w3->sizeY, 0, GL_RGB,GL_UNSIGNED_BYTE, w3->data);
    
    glBindTexture(GL_TEXTURE_2D, pared[0]);
    glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR);
    glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR);
    glTexImage2D(GL_TEXTURE_2D, 0, 3, w4->sizeX, w4->sizeY, 0, GL_RGB,GL_UNSIGNED_BYTE, w4->data);
    
    glBindTexture(GL_TEXTURE_2D, madera[0]);
    glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR);
    glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR);
    glTexImage2D(GL_TEXTURE_2D, 0, 3, w5->sizeX, w5->sizeY, 0, GL_RGB,GL_UNSIGNED_BYTE, w5->data);
    
}

void setCar(Car* car,GLdouble posx, GLdouble posz){
    car->x = posx;
    car->z = posz;
    car->y = 0.0;
    car->vision = 0.0;
    car->ang_ruedas = 0.0;
    car->v_mag = 0.0;
    car->a_mag = 0.0;    
    car->vc_mag = 0.0;
    car->vc_dir = 0.0;
    car->acelera=0;
    car->time_units=0;
    car->vy = 0;
    car->ang_canon=45;
    car->anim_canon=0;
    car->balas = 10;
    car->vidas = 3;
    car->hit = car->salta = 0;
    car->nodo = car->nodot = car->nodosig = -1;
    car->llegue = 0;
}

void gameStats(Car* yo,Car* com,GLint *mode){
    // Si alguien tiene 0 vidas se termino el juego!!
    if(yo->vidas == 0){
        *mode = 0;
        printf("Game Over!! \nYou Lost :(\n");
    }
    else if(com->vidas == 0){
        *mode = 0;
        printf("Game Over!! \nYou Won :)\n");
    }
    if(*mode == 0){
        // Reinicio el juego
        setCar(yo,-80.0,-80.0);
        setCar(com,95.0,120.0);
        com->nodo = 38;
        com->nodosig = 38;
        com->nodot = 38;
        setItems();
    }
}

void construirEdificio(){
    glColor3f(1.0,1.0,1.0);
    glEnable(GL_TEXTURE_2D);
    glPushMatrix();
        glBindTexture(GL_TEXTURE_2D, edificio[0]);
        glBegin(GL_QUADS);
            // pared norte
            glTexCoord2f(0.0,0.0);glVertex3f(-10,-0.38f,-10);
            glTexCoord2f(1.0,0.0);glVertex3f(-10,-0.38f,10);
            glTexCoord2f(1.0,1.0);glVertex3f(-10,29.38f,10);
            glTexCoord2f(0.0,1.0);glVertex3f(-10,29.38f,-10);
        glEnd();
        glBindTexture(GL_TEXTURE_2D, edificio[1]);
        glBegin(GL_QUADS);
            // pared sur
            glTexCoord2f(0.0,0.0);glVertex3f(10,-0.38f,-10);
            glTexCoord2f(1.0,0.0);glVertex3f(10,-0.38f,10);
            glTexCoord2f(1.0,1.0);glVertex3f(10,29.38f,10);
            glTexCoord2f(0.0,1.0);glVertex3f(10,29.38f,-10);
            // pared oeste
            glTexCoord2f(0.0,0.0);glVertex3f(-10,-0.38f,-10);
            glTexCoord2f(1.0,0.0);glVertex3f(10,-0.38f,-10);
            glTexCoord2f(1.0,1.0);glVertex3f(10,29.38f,-10);
            glTexCoord2f(0.0,1.0);glVertex3f(-10,29.38f,-10);        
            // pared este
            glTexCoord2f(0.0,0.0);glVertex3f(-10,-0.38f,10);
            glTexCoord2f(1.0,0.0);glVertex3f(10,-0.38f,10);
            glTexCoord2f(1.0,1.0);glVertex3f(10,29.38f,10);
            glTexCoord2f(0.0,1.0);glVertex3f(-10,29.38f,10);
        glEnd();
    glPopMatrix();
    glDisable(GL_TEXTURE_2D);
}

void unaPared(GLdouble f,GLdouble a,GLint l){
    GLint i;
    for(i=0;i<l;i++){
        glBindTexture(GL_TEXTURE_2D, pared[0]);
        GLdouble j;
        for(j=-0.38;j<a;j+=0.5){
            glBegin(GL_QUADS);
                glTexCoord2f(0.0,0.0);glVertex3f(f,j,i);
                glTexCoord2f(1.0,0.0);glVertex3f(f,j,i+1);
                glTexCoord2f(1.0,1.0);glVertex3f(f,j+0.5,i+1);
                glTexCoord2f(0.0,1.0);glVertex3f(f,j+0.5,i);                
            glEnd();
        }
    }
}

void unaTapa(GLdouble f, GLdouble a){
    GLdouble j;
    glColor3f(1.0,1.0,1.0);
    glEnable(GL_TEXTURE_2D);
    glBindTexture(GL_TEXTURE_2D, pared[0]);
    for(j=-0.38;j<a;j+=0.5){
        glBegin(GL_QUADS);
            glTexCoord2f(0.0,0.0);glVertex3f(f,j,0);
            glTexCoord2f(1.0,0.0);glVertex3f(f,j,0.2);
            glTexCoord2f(1.0,1.0);glVertex3f(f,j+0.5,0.2);
            glTexCoord2f(0.0,1.0);glVertex3f(f,j+0.5,0);                
        glEnd();
    }
    glDisable(GL_TEXTURE_2D);
}

void construirPared(){
    glColor3f(1.0,1.0,1.0);
    glEnable(GL_TEXTURE_2D);
    glBindTexture(GL_TEXTURE_2D, pared[0]);
    glPushMatrix();
        unaPared(0.0,3.0,150);
        unaPared(0.2,3.0,150);    
    glPopMatrix();
    glPushMatrix();
        glRotatef(90,0,1,0);
        glTranslatef(-0.2,0,0);
        unaPared(0.0,3.0,50);
        unaPared(0.2,3.0,50);
    glPopMatrix();    
    glPushMatrix();   
        glTranslatef(50,0,0);
        unaTapa(0.0,3.0);
    glPopMatrix();    
    glPushMatrix();   
        glRotatef(90,0,1,0); 
        glTranslatef(-150,0,0);
        unaTapa(0.0,3.0);
    glPopMatrix();    
    glPushMatrix();   
        glRotatef(-90,0,0,1);
        glTranslatef(-3.12,0.38,0);
        unaTapa(0.0,49.62);
    glPopMatrix();    
    glPushMatrix();   
        glRotatef(-90,0,1,0);
        glRotatef(-90,0,0,1);        
        glTranslatef(-3.12,0.38,-0.2);
        unaTapa(0.0,149.62);
    glPopMatrix();   
    glDisable(GL_TEXTURE_2D);
}

void construirMurito(){
    glColor3f(1.0,1.0,1.0);
    glEnable(GL_TEXTURE_2D);
    glBindTexture(GL_TEXTURE_2D, pared[0]);
    glPushMatrix();
        unaPared(0.0,0.5,100);
        unaPared(0.2,0.5,100);    
    glPopMatrix();
    glPushMatrix();
        glRotatef(90,0,1,0);
        glTranslatef(-0.2,0,0);
        unaPared(0.0,0.5,100);
        unaPared(0.2,0.5,100);
    glPopMatrix();    
    glPushMatrix();   
        glTranslatef(100,0,0);
        unaTapa(0.0,0.5);
    glPopMatrix();    
    glPushMatrix();   
        glRotatef(90,0,1,0); 
        glTranslatef(-100,0,0);
        unaTapa(0.0,0.5);
    glPopMatrix();    
    glPushMatrix();   
        glRotatef(-90,0,0,1);
        glTranslatef(-0.62,0.38,0);
        unaTapa(0.0,99.62);
    glPopMatrix();    
    glPushMatrix();   
        glRotatef(-90,0,1,0);
        glRotatef(-90,0,0,1);        
        glTranslatef(-0.62,0.38,-0.2);
        unaTapa(0.0,99.62);
    glPopMatrix();   
    glDisable(GL_TEXTURE_2D);
}

void construirRampa(){
    glColor3f(1.0,1.0,1.0);
    glEnable(GL_TEXTURE_2D);
    glBindTexture(GL_TEXTURE_2D, madera[0]);
    // rampa
    glPushMatrix();
        glBegin(GL_QUADS);
            glTexCoord2f(0.0,0.0);glVertex3f(0,-0.38,0);
            glTexCoord2f(1.0,0.0);glVertex3f(0,-0.38,10);
            glTexCoord2f(1.0,1.0);glVertex3f(25,10,10);
            glTexCoord2f(0.0,1.0);glVertex3f(25,10,0);  
        glEnd();    
        glBegin(GL_QUADS);
            glTexCoord2f(1.0,1.0);glVertex3f(25,10,10);
            glTexCoord2f(0.0,1.0);glVertex3f(25,10,0);
            glTexCoord2f(0.0,0.0);glVertex3f(25,-0.38,0);
            glTexCoord2f(1.0,0.0);glVertex3f(25,-0.38,10);
        glEnd();
    glPopMatrix();
    // paredes
    glPushMatrix();
        glRotatef(90,0,1,0);
        unaPared(0.0,10,25);
        unaPared(0.2,10,25);    
    glPopMatrix();
    glPushMatrix();
        glTranslatef(0,0,10.2);
        glRotatef(90,0,1,0);
        unaPared(0.0,10,25);
        unaPared(0.2,10,25);    
    glPopMatrix();    
    glPushMatrix();
        glTranslatef(0,0,-0.2);
        unaTapa(0.0,10);
    glPopMatrix();
    glPushMatrix();
        glTranslatef(0,0,10);
        unaTapa(0.0,10);
    glPopMatrix();
    glPushMatrix();
        glTranslatef(25,0,-0.2);
        unaTapa(0.0,10);
    glPopMatrix();
    glPushMatrix();
        glTranslatef(25,0,10);
        unaTapa(0.0,10);
    glPopMatrix();
    glPushMatrix();        
        glRotatef(-90,0,0,1);       
        glTranslatef(-10.12,0.38,-0.2);
        unaTapa(0.0,24.5);
    glPopMatrix();
    glPushMatrix();
        glRotatef(-90,0,0,1);       
        glTranslatef(-10.12,0.38,10);
        unaTapa(0.0,24.5);
    glPopMatrix();   
    glDisable(GL_TEXTURE_2D);
}

void cargarMapa(char* path){
    FILE* f = fopen(path,"r");
    GLint i,xi,zi,xf,zf,a,warn;
    // Cargar Paredes
    warn = fscanf(f,"%d",&nr);
    rectas = (Linea*)malloc(sizeof(Linea)*nr);
    for(i=0;i<nr;i++){        
        warn = fscanf(f,"%d %d %d %d %d %d",&xi,&zi,&xf,&zf,&a,&rectas[i].hor);
        rectas[i].xi = (double)xi;
        rectas[i].zi = (double)zi;
        rectas[i].xf = (double)xf;
        rectas[i].zf = (double)zf;
        rectas[i].a = (double)a;
    }
    // Cargar Edificios
    warn = fscanf(f,"%d",&nedif);
    edifs = (Edif*)malloc(sizeof(Edif)*nedif);
    for(i=0;i<nedif;i++){        
        warn = fscanf(f,"%d %d %d %d",&xi,&xf,&zi,&zf);
        edifs[i].xi = (double)xi;
        edifs[i].xf = (double)xf;
        edifs[i].zi = (double)zi;
        edifs[i].zf = (double)zf;
    }
    // Cargar Rampas
    warn = fscanf(f,"%d",&nramp);
    rampas = (Rampa*)malloc(sizeof(Rampa)*nramp);
    for(i=0;i<nramp;i++){        
        warn = fscanf(f,"%d %d %d %d %d",&xi,&xf,&zi,&zf,&a);
        rampas[i].xi = (double)xi;
        rampas[i].xf = (double)xf;
        rampas[i].zi = (double)zi;
        rampas[i].zf = (double)zf;
        rampas[i].normal = (double)a;
    }
    // Cargar Grafo
    warn = fscanf(f,"%d",&nn);
    nodos = (Nodo*)malloc(sizeof(Nodo)*nn);
    GLint x1,z1,x2,z2,x3,z3,xp,zp,v1,v2,v3;
    for(i=0;i<nn;i++){        
        warn = fscanf(f,"%d %d %d %d %d %d %d %d %d %d %d",&x1,&z1,&x2,&z2,&x3,&z3,&xp,&zp,&v1,&v2,&v3);
        nodos[i].x1 = (double)x1;
        nodos[i].z1 = (double)z1;
        nodos[i].x2 = (double)x2;
        nodos[i].z2 = (double)z2;
        nodos[i].x3 = (double)x3;
        nodos[i].z3 = (double)z3;
        nodos[i].x = (double)xp;
        nodos[i].z = (double)zp;
        nodos[i].v1 = (double)v1;
        nodos[i].v2 = (double)v2;
        nodos[i].v3 = (double)v3;
        nodos[i].visitado = 0;
        nodos[i].yo_aceite = 0;
        nodos[i].com_aceite = 0;
        nodos[i].time = 0;
    }
}

int cual_lado(GLdouble x,GLdouble y,GLdouble x1,GLdouble y1,GLdouble x2,GLdouble y2){
    GLdouble distancia;
    distancia = (y - y1) * (x2 - x1) - (y2 - y1) * (x - x1);
    if (distancia > 0)
        return(-1);
    else if (distancia < 0)
        return(1);
    else
        return(0);
}

int enNodo(GLdouble x, GLdouble z, Nodo* nod){
    GLint lado1,lado2,lado3;
    lado1 = cual_lado(x,z,nod->x1,nod->z1,nod->x2,nod->z2);
    lado2 = cual_lado(x,z,nod->x2,nod->z2,nod->x3,nod->z3);
    lado3 = cual_lado(x,z,nod->x3,nod->z3,nod->x1,nod->z1);

    if (lado1 == 0 && lado2 == 0)
        return(1);
    if (lado1 == 0 && lado3 == 0)
        return(1);
    if (lado2 == 0 && lado3 == 0)
        return(1);
    if (lado1 == 0 && (lado2 == lado3))
        return(1);
    if (lado2 == 0 && (lado1 == lado3))
        return(1);
    if (lado3 == 0 && (lado1 == lado2))
        return(1);
    if ((lado1 == lado2) && (lado2 == lado3))
        return(1);
    return(0);   
}

GLdouble IDAstar(Car* c,GLint n,GLint nt,GLint d,GLint depth,GLdouble w){
    if (d == depth){
        if (n == nt) {c->llegue = 1;return (-1)*w;}
        return w;
    }
    
    nodos[n].visitado = 1;
    
    GLdouble cost1,cost2,cost3;
    GLdouble peso1,peso2,peso3;
    
    peso1 = peso2 = peso3 = 10000000.0;
    
    GLint v1 = nodos[n].v1;
    GLint v2 = nodos[n].v2;
    GLint v3 = nodos[n].v3;
    
    if (!(nodos[v1].visitado)){
        cost1 = sqrt(pow((nodos[v1].x-nodos[n].x),2)+pow((nodos[v1].z-nodos[n].z),2));
        peso1 = IDAstar(c,v1,nt,d+1,depth,w+cost1);
    }    
    if (v2 != -1 && !(nodos[v2].visitado)){
        cost2 = sqrt(pow((nodos[v2].x-nodos[n].x),2)+pow((nodos[v2].z-nodos[n].z),2));
        peso2 = IDAstar(c,v2,nt,d+1,depth,w+cost2);
    }
    if (v3 != -1 && !(nodos[v3].visitado)){
        cost3 = sqrt(pow((nodos[v3].x-nodos[n].x),2)+pow((nodos[v3].z-nodos[n].z),2));
        peso3 = IDAstar(c,v3,nt,d+1,depth,w+cost3);
    }
    
    nodos[n].visitado = 0;
    
    if (v2 == -1){
        if (d == 0) return 1.0;
        return peso1;
    }
    if (v3 == -1){
        if (d == 0) {
            if (peso1 <= peso2) return 1.0;
            else                return 2.0;
        }
        if (peso1 <= peso2) return peso1;
        else                return peso2;
    }
    if (d == 0) {
        if      (peso1 <= peso2 && peso1 <= peso3) return 1.0;
        else if (peso2 <= peso1 && peso2 <= peso3) return 2.0;
        else                                       return 3.0;
    }
    if      (peso1 <= peso2 && peso1 <= peso3) return peso1;
    else if (peso2 <= peso1 && peso2 <= peso3) return peso2;
    else                                       return peso3;
    
}

void haciaDonde(Car* car){
    GLint depth;
    GLdouble res=-1;
    for (depth=0;!car->llegue;depth++){
        res = IDAstar(car,car->nodo,car->nodot,0,depth,0.0);
    }
    GLint r = (int)res;
    if (r==1) car->nodosig = nodos[car->nodo].v1;
    if (r==2) car->nodosig = nodos[car->nodo].v2;
    if (r==3) car->nodosig = nodos[car->nodo].v3;   
    car->llegue = 0;
}

GLint enUltimaGota(Car* car,OilTrace* rastro){
    if (rastro->gotaN == 0 && rastro->vuelta == 0) return 1;
    GLint foo = rastro->gotaN-1;
    if (foo == -1) foo = 99;
    if (sqrt(pow(rastro->aceiteXZ[foo][0]-car->x,2)+
        pow(rastro->aceiteXZ[foo][1]-car->z,2))<2) return 0;
    else return 1;
}

void rastroAceite(Car* yo,Car* com,OilTrace* yo_rastro,OilTrace* com_rastro){
    int i;
    for(i=0;i<200;i++){
        if (yo_rastro->aceiteXZ[i][2]>0){
            yo_rastro->aceiteXZ[i][2] -= 0.010;
            if (yo_rastro->aceiteXZ[i][2] <= 0){
                nodos[whereIs(yo_rastro->aceiteXZ[i][0],
                                        yo_rastro->aceiteXZ[i][1])].yo_aceite--;
            }
        }
        if (com_rastro->aceiteXZ[i][2]>0){
            com_rastro->aceiteXZ[i][2] -= 0.010;
            if (com_rastro->aceiteXZ[i][2] <= 0){
                nodos[whereIs(com_rastro->aceiteXZ[i][0],
                                                 com_rastro->aceiteXZ[i][1])].com_aceite--;
            }
        }
    }
    if (yo->vidas == 1 && enUltimaGota(yo,yo_rastro)){
        yo_rastro->aceiteXZ[yo_rastro->gotaN][0] = yo->x;
        yo_rastro->aceiteXZ[yo_rastro->gotaN][1] = yo->z;
        yo_rastro->aceiteXZ[yo_rastro->gotaN][2] = 3.000;
        nodos[whereIs(yo->x,yo->z)].yo_aceite++;
        yo_rastro->gotaN++;
        if (yo_rastro->gotaN == 200){
            yo_rastro->vuelta = 1;
            yo_rastro->gotaN = 0;
        }
        if (yo_rastro->vuelta){
            yo_rastro->gotaP++;
            yo_rastro->gotaP%=200;
        }        
    }
    if (com->vidas == 1 && enUltimaGota(com,com_rastro)){
        com_rastro->aceiteXZ[com_rastro->gotaN][0] = com->x;
        com_rastro->aceiteXZ[com_rastro->gotaN][1] = com->z;
        com_rastro->aceiteXZ[com_rastro->gotaN][2] = 3.000;
        nodos[whereIs(com->x,com->z)].com_aceite++;
        com_rastro->gotaN++;
        if (com_rastro->gotaN == 200){
            com_rastro->vuelta = 1;
            com_rastro->gotaN = 0;
        }
        if (com_rastro->vuelta){
            com_rastro->gotaP++;
            com_rastro->gotaP%=200;
        }        
    }
}

void setItems(){
    amno = rand()%nn;
    vida = rand()%nn;
    printf(" balas en nodo %d \n vida en nodo %d \n",amno,vida);
}

void dibujaCruz(){
    glPushMatrix();
        glScalef(1,3,1);
        glutSolidCube(0.5);        
    glPopMatrix();
    glPushMatrix();
        glScalef(3,1,1);
        glutSolidCube(0.5);
    glPopMatrix();
}
